#include <iostream>
#include <vector>
#include <unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/wait.h>
#include"Task.hpp"

std::vector<task_t> tasks;
// 先描述
class channel
{
public:
    channel(int comfd, pid_t slaverid, std::string processname)
        : _comdfd(comfd), _slaverid(slaverid), _processname(processname)
    {
    }
    // private:
public:
    int _comdfd;              // 发送任务的文件描述符
    pid_t _slaverid;          // 子进程的pid
    std::string _processname; // 子进程的名字，方便打日志
};

void sliver()
{
    while(true)
    {
        int cmdcode=0;
        int n=read(0,&cmdcode,sizeof(int));
        if(n==sizeof(int))
        {
            std::cout<<"slaver get a command: "<<getpid()<<" comdcode:"<<cmdcode<<std::endl;
            if(cmdcode>=0 &&cmdcode<tasks.size())
            {
                tasks[cmdcode]();
            }
        }
        if(n==0)
            break;
    }
}
//输出型参数 *
//输入型参数const &
//输入输出型参数 &
void InitSliver(std::vector<channel>* channels)
{
    //确保每一个子进程都只有一个写端
    std::vector<int>oldfd;
    for (int i = 0; i < 10; i++)
    {
        int pipefd[2];
        // 建立管道
        int n = pipe(pipefd);
        if (n < 0)
        {
            perror("pipe");
            return;
        }
        // 创建父子进程
        pid_t id = fork();
        if (id < 0)
        {
            perror("fork");
            return;
        }
        else if (id == 0) // child
        {
            for(auto&fd:oldfd)
                close(fd);
            close(pipefd[1]); // 关闭一端
            dup2(pipefd[0], 0);
         
            close(pipefd[0]);
            sliver();
            std::cout<<"process: "<<getpid()<<" quit"<<std::endl;
            exit(0);
            
        }
        // father
        
            close(pipefd[0]); // 关闭一端
            std::string processname = "process" + std::to_string(i);
            channels->push_back({pipefd[1], id, processname});
            oldfd.push_back(pipefd[1]);
            
            // sleep(1);
    }
    
}

void Debug(std::vector<channel>&channels)
{
    for(auto &e:channels)
        std::cout << e._comdfd << ":" << e._slaverid << ":" << e._processname << std::endl;
}
void Menu()
{
    std::cout << "################################################" << std::endl;
    std::cout << "# 1. 刷新日志             2. 刷新出来野怪        #" << std::endl;
    std::cout << "# 3. 检测软件是否更新      4. 更新用的血量和蓝量  #" << std::endl;
    std::cout << "#                         0. 退出               #" << std::endl;
    std::cout << "#################################################" << std::endl;
}

void ctrlSlaver(const std::vector<channel>& channels)
{
    int count=0;
    while(true)
    {
        int select=0;
        Menu();
        std::cout<<"Please Enter# "<<std::endl;
        std::cin>>select;

        if(select<=0 ||select>5)
            break;
        
        //选择任务
        // int cmdcode=rand()%tasks.size();
        int cmdcode=select-1;
        //选择进程
        int processpos=rand()%tasks.size();
        std::cout<<"father say:"<<"cmdcode:"<<cmdcode<<" already send to "<<channels[processpos]._slaverid<<
            " process name: "<<channels[processpos]._processname<<std::endl;
        //发送任务
        write(channels[processpos]._comdfd,&cmdcode,sizeof(cmdcode));
        count++;
        if(count>=5)
            break;
        sleep(1);
    }

}
void QuitSlaver(const std::vector<channel>& channels)
{
    for(const auto e:channels)
    {
        close(e._comdfd);
        waitpid(e._slaverid,nullptr,0);
    }
}

int main()
{
    LoadTask(&tasks);
    //种下随机数种子
    srand(time(nullptr));
    // 再组织
    std::vector<channel> channels;
    // 初始化，创建多个进程，建立框架！
    InitSliver(&channels);
    // Debug(channels);
    // std::cout<<channels[0]._comdfd<<":"<<channels[0]._slaverid<<":"<<channels[0]._processname<<std::endl;
    //控制进程
    ctrlSlaver(channels);
    QuitSlaver(channels);
    return 0;
}